#include <ros/ros.h>
#include <actionlib/client/simple_action_client.h>
#include "learn_actionlib/FibonacciAction.h"

class FibonacciActionClient {
 public:
  FibonacciActionClient(std::string action_name) 
    : ac_(action_name, true){
    ROS_INFO("Waiting for action server to start.");
    ac_.waitForServer();
    ROS_INFO("Action server started, sending goal.");
  }

  void SendGoalToServer(int order) {
    learn_actionlib::FibonacciGoal goal;
    goal.order = order;
    ac_.sendGoal(goal, 
      boost::bind(&FibonacciActionClient::DoneCb, this, _1, _2),
      boost::bind(&FibonacciActionClient::ActiveCb, this),
      boost::bind(&FibonacciActionClient::FeedbackCb, this, _1));
  }

 private:
  actionlib::SimpleActionClient<learn_actionlib::FibonacciAction> ac_;


  // Called once when the goal completes
  void DoneCb(const actionlib::SimpleClientGoalState& state,
              const learn_actionlib::FibonacciResultConstPtr& result) {
    ROS_INFO("Finished in state [%s]", state.toString().c_str());
    ROS_INFO("Answer: %i", result->sequence.back());
    ros::shutdown();
  }

  // Called once when the goal becomes active
  void ActiveCb() {
    ROS_INFO("Goal just went active");
  }

  // Called every time feedback is received for the goal
  void FeedbackCb(const learn_actionlib::FibonacciFeedbackConstPtr& feedback) {
    ROS_INFO("Got Feedback of length %lu", feedback->sequence.size());
    if (feedback->sequence.size() >= 1)
      ROS_INFO("Feedback value: sequence[%d]=%d", static_cast<int>(feedback->sequence.size()-1), feedback->sequence.back());
  }
};


int main(int argc, char** argv) {
  ros::init(argc, argv, "fibonacci_action_client");

  FibonacciActionClient client_node("fibonacci");
  client_node.SendGoalToServer(20);
  ros::spin();

  return 0;
}
